package org.nativejpa.query;

import java.util.Collection;
import java.util.List;

import org.nativejpa.mapping.ColumnMetadata;
import org.nativejpa.mapping.EntityRepository;
import org.nativejpa.mapping.JoinColumnMetadata;

/**
 * SQL Template
 *
 * @author <a href="mailto:jfox.young@gmail.com">Young Yang</a>
 * @create 2009-3-17 15:41:46
 */
public class SQLTemplate {

    public final static String DEFAULT_CACHE_NAME = "DEFAULT_CACHE";    

    public static final QueryRepository queryRepository = QueryRepository.getInstance();    

    protected String templateSQL;

    protected Class<?> resultClass; // default void.class

    protected String resultsetMapping = "";

    public SQLTemplate(String sqlTemplate, Class<?> resultClass, String resultsetMapping) {
        this.templateSQL = sqlTemplate;
        this.resultClass = resultClass;
        if(resultsetMapping != null && !resultsetMapping.trim().equals("")) {
            this.resultsetMapping = resultsetMapping;
        }
    }

    public Class<?> getColumnClass(String columnName) {
        if (!resultClass.equals(void.class)) { // resultClass is set
            ColumnMetadata columnMetadata = EntityRepository.getInstance().getColumnMetadata(getResultClass(), columnName);
            if (columnMetadata == null) {
                return null;
            }
            else {
                return columnMetadata.getFieldType();
            }
        }
        else { // resultsetMapping is set
            ResultsetMapping sqlResultsetMapping = QueryRepository.getInstance().getResultsetMapping(resultsetMapping);
            List<EntityResultMapping> entityResultMappings = sqlResultsetMapping.getEntityResults();
            for(EntityResultMapping entityResultMapping : entityResultMappings){
                String fieldColumnName = entityResultMapping.getFieldName(columnName); // may set FieldResult mapping
                ColumnMetadata columnMetadata = EntityRepository.getInstance().getColumnMetadata(entityResultMapping.getEntityClass(), fieldColumnName);
                if (columnMetadata != null) {
                    return columnMetadata.getFieldType();
                }
            }
            return null;
        }
    }

    /**
     * return all JoinColumnMetadata
     */
    public Collection<JoinColumnMetadata> getJoinColumnMetadatas() {
        return EntityRepository.getInstance().getJoinColumnEntries(getResultClass());
    }

    public String getTemplateSQL() {
        return templateSQL;
    }

    public String getTemplateSQL(String dbProductName) {
        // ignore dbtype
        return getTemplateSQL();
    }

    public Class<?> getResultClass() {
        return this.resultClass;
    }

    public String getResultsetMapping() {
        return resultsetMapping;
    }

    public boolean isGenerated() {
        return false;
    }

    // create Query for JoinColumn 
    public NamedSQLTemplate createJoinColumnQueryNamedSQLTemplate(JoinColumnMetadata joinColumnMetadata){
        String name = "_AUTO_JOINCOLUMN_" + joinColumnMetadata.getDefineClass().getName() + "_" + joinColumnMetadata.getName() + "_" + joinColumnMetadata.getTargetEntity().getName();
        if(!queryRepository.containsNamedSQLTemplate(name)) {
            NamedSQLTemplate sqlTemplate = null;
            if(joinColumnMetadata.getColumnDefinition() != null && joinColumnMetadata.getColumnDefinition().trim().length() != 0 ) {
                // use columnDefinition as mapping sql
                sqlTemplate = new NamedSQLTemplate(name, joinColumnMetadata.getColumnDefinition(), joinColumnMetadata.getTargetEntity(), "", joinColumnMetadata.getDefineClass(), DEFAULT_CACHE_NAME);
            }
            else {
                // create mapping sql
//                String sql = "SELECT * FROM " + joinColumnMetadata.getReferencedTableName() + " WHERE " + joinColumnMetadata.getReferencedColumnName()  + " = $" + EntityRepository.getInstance().getPKColumnMetadata(joinColumnMetadata.getDefineClass()).getName();
                String sql = "SELECT * FROM " + joinColumnMetadata.getReferencedTableName() + " WHERE " + joinColumnMetadata.getReferencedColumnName()  + " = $" + joinColumnMetadata.getName();
                sqlTemplate = new NamedSQLTemplate(name, sql, joinColumnMetadata.getTargetEntity(), "", joinColumnMetadata.getDefineClass(), joinColumnMetadata.getDefineClass().getName());
            }
            queryRepository.registerNamedSQLTemplate(sqlTemplate);
        }
        return queryRepository.getNamedSQLTemplate(name);
    }
}
